package com.neusoft.SPNursingHome.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.neusoft.SPNursingHome.dao.BedDao;
import com.neusoft.SPNursingHome.dao.BedRecordDao;
import com.neusoft.SPNursingHome.dao.CheckInRecordDao;
import com.neusoft.SPNursingHome.dao.ClientCareItemDao;
import com.neusoft.SPNursingHome.dao.ClientDao;
import com.neusoft.SPNursingHome.po.ClientCheckInDto;
import com.neusoft.SPNursingHome.po.*;
import jakarta.annotation.Resource;
import com.neusoft.SPNursingHome.service.ClientService;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.*;

import static java.lang.reflect.Array.set;
import static net.sf.jsqlparser.util.validation.metadata.NamedObject.column;

@Service
public class ClientServiceImpl implements ClientService{
    @Resource
    @Autowired
    private ClientDao clientDao;
    @Resource
    private BedRecordDao bedRecordDao;
    @Resource
    private BedDao bedDao;
    @Resource
    private CheckInRecordDao checkInRecordDao;
    @Autowired
    private ClientCareItemDao clientCareItemDao;
    //客户列表&查询
    @Override
    public ResponseBean<IPage<Client>> findClientsByCriteria(long pageNum, long pageSize,  Map<String, Object> query) {
        try {
            IPage<Client> page = new Page<>(pageNum, pageSize);
            QueryWrapper<Client> wrapper = new QueryWrapper<>();
            if (query != null) {
                String clientName = (String) query.get("clientName");
                if (clientName != null && !clientName.trim().isEmpty()) {
                    wrapper.like("client_name", clientName);
                }
                String clientType = (String) query.get("clientType");
                if (clientType != null && !clientType.trim().isEmpty()) {
                    wrapper.eq("client_type", clientType);
                }
            }
            wrapper.orderByAsc("client_id");
            wrapper.eq("client_status", 1); // 只查询状态为1的客户，即未被逻辑删除的客户
            IPage<Client> resultPage = clientDao.selectPage(page, wrapper);
            return new ResponseBean<>(resultPage);
        } catch (Exception e) {
            return new ResponseBean<>(500, "查询客户信息时发生服务器内部错误");
        }
    }

    // 更新单个客户的状态 (删除或恢复)
    @Override
    public ResponseBean<Void> updateClientStatus(Integer clientId, Integer status) {
        // 1. 查找客户信息
        Client client = clientDao.selectById(clientId);
        if (client == null) {
            return new ResponseBean<>(404, "操作失败，客户不存在");
        }
        Integer bedId = client.getBedId();

        if (status == 0) { // --- 执行逻辑删除操作 ---
            // 更新客户状态
            client.setClientStatus(0);
            clientDao.updateById(client);

            // 如果客户占用了床位，则释放床位并终止床位使用记录
            if (bedId != null) {
                // a. 修改床位状态为空闲
                Bed bed = bedDao.selectById(bedId);
                bed.setBedStatus("空闲");
                bedDao.updateById(bed);

                // b. 逻辑删除床位使用记录
                UpdateWrapper<BedRecord> brWrapper = new UpdateWrapper<>();
                brWrapper.eq("client_id", clientId)
                        .eq("bed_record_status", 1) // 只处理正在使用的记录
                        .set("bed_record_status", 0) // 状态置为0
                        .set("bed_end_time", new Date()); // 记录结束时间
                bedRecordDao.update(null, brWrapper);
            }
        } else if (status == 1) { // --- 执行撤销删除 (恢复) 操作 ---
            // 更新客户状态
            client.setClientStatus(1);
            clientDao.updateById(client);
            // 如果客户之前有关联的床位，则尝试恢复占用
            if (bedId != null) {
                // a. 检查床位是否仍为空闲，防止在删除期间被他人占用
                Bed currentBed = bedDao.selectById(bedId);
                System.out.println("c" + currentBed + " " + currentBed.getBedStatus());
                if (currentBed != null && !"空闲".equals(currentBed.getBedStatus())) {
                    // 床位已被占用，抛出异常，整个事务将回滚
                    throw new RuntimeException("撤销失败：该客户原床位已被他人占用！");
                }
                // b. 将床位状态重新设置为有人
                currentBed.setBedStatus("有人");
                bedDao.updateById(currentBed);

                // c. 恢复床位使用记录
                // 找到该客户最近一条结束的记录并重新激活
                UpdateWrapper<BedRecord> brWrapper = new UpdateWrapper<>();
                brWrapper.eq("client_id", clientId)
                        .orderByDesc("bed_end_time") // 按结束时间降序
                        .last("LIMIT 1") // 取最新的一条
                        .set("bed_record_status", 1) // 状态置为1
                        .set("bed_end_time", null);    // 清空结束时间
                bedRecordDao.update(null, brWrapper);
            }
        } else {
            return new ResponseBean<>(400, "无效的操作状态");
        }

        return new ResponseBean<>(200, "操作成功");
    }

     //批量更新客户的状态
    @Override
    @Transactional
    public ResponseBean<Void> updateClientStatusBatch(List<Integer> clientIds, Integer status) {
        if (clientIds == null || clientIds.isEmpty()) {
            return new ResponseBean<>(400, "客户ID列表不能为空");
        }

        // 使用 UpdateWrapper 和 `in` 条件来执行一条SQL完成批量更新，效率更高
        UpdateWrapper<Client> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .in("client_id", clientIds) // 条件: WHERE client_id IN (?, ?, ...)
                .set("client_status", status); // 更新: SET client_status = ?

        clientDao.update(null, updateWrapper);

        return new ResponseBean<>(200, "批量操作成功");
    }

    //单个客户信息（编辑回显）
    @Override
    public ResponseBean<ClientCheckInDto> getClientDetailsForEdit(Integer clientId) {
        // 直接调用我们自定义的DAO方法，一步到位获取所有数据
        ClientCheckInDto dto = clientDao.findClientDetailsForUpdate(clientId);
        if (dto == null) {
            return new ResponseBean<>(404, "未找到客户");
        }
        return new ResponseBean<>(dto);
    }

    //修改客户信息
    @Override
    @Transactional
    public ResponseBean<Void> updateClientInfo(ClientCheckInDto dto) {

        Client clientToUpdate = clientDao.selectById(dto.getClientId());
        clientToUpdate.setClientType(dto.getClientType());
        clientToUpdate.setClientName(dto.getClientName());
        clientToUpdate.setClientAge(dto.getClientAge());
        clientToUpdate.setDateOfBirth(dto.getDateOfBirth());
        clientToUpdate.setClientGender(dto.getClientGender());
        clientToUpdate.setClientCardNumber(dto.getClientCardNumber());
        clientToUpdate.setBloodType(dto.getBloodType());
        clientToUpdate.setClientPhone(dto.getClientPhone());
        clientToUpdate.setFamilyMember(dto.getFamilyMember());

        int clientRows = clientDao.updateById(clientToUpdate);
        if (clientRows == 0) {
            throw new RuntimeException("更新客户信息失败，客户可能不存在");
        }

        // 2. 如果合同到期时间发生改变，则更新 CheckInRecord 和 BedRecord
        if (dto.getContractEndTime() != null) {
            // a. 更新最新一条入住记录的合同到期时间
            UpdateWrapper<CheckInRecord> cirWrapper = new UpdateWrapper<>();
            // 找到最新的那条入住记录并更新
            // 注意: UpdateWrapper不支持复杂的子查询，所以这里我们假设一个客户只有一条总入住记录需要更新
            // 如果业务允许多次入住，这里的逻辑需要更复杂地先查询ID再更新
            cirWrapper.eq("client_id", dto.getClientId())
                    .orderByDesc("check_in_time")
                    .last("LIMIT 1");
            CheckInRecord cirToUpdate = new CheckInRecord();
            cirToUpdate.setContractEndTime(dto.getContractEndTime());
            checkInRecordDao.update(cirToUpdate, cirWrapper);

            // b. 更新当前生效的床位记录的退住时间
            // 这是正确的做法：找到 bed_record_status = 1 的那条记录
            UpdateWrapper<BedRecord> brWrapper = new UpdateWrapper<>();
            brWrapper.eq("client_id", dto.getClientId())
                    .eq("bed_record_status", 1) // 定位到当前正在使用的记录
                    .set("bed_end_time", dto.getContractEndTime()); // 将其退住时间设为新的合同到期日

            bedRecordDao.update(null, brWrapper);
        }

        return new ResponseBean<>(200, "更新成功");
    }

    @Override
    public ResponseBean<IPage<Client>> getMyManagedClients(long pageNum, long pageSize, Integer adId, String clientName) {
        Page<Client> page = new Page<>(pageNum, pageSize);
        Map<String, Object> query = new HashMap<>();
        query.put("adId", adId);
        query.put("clientName", clientName);

        IPage<Client> resultPage = clientDao.findClientsByCarerId(page, query);
        return new ResponseBean<>(resultPage);
    }
    //导出客户信息
    @Override
    public ResponseBean<byte[]> exportAllClients() {
        // 使用 try-with-resources 确保资源（如Workbook和OutputStream）被自动关闭
        try (Workbook workbook = new XSSFWorkbook();
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

            // 1. 创建一个名为 "客户信息" 的工作表 (Sheet)
            Sheet sheet = workbook.createSheet("客户信息");

            // 2. 定义表头内容
            String[] headers = {
                    "客户ID", "客户姓名", "客户类型", "性别", "年龄",
                    "出生日期", "身份证号", "血型", "家属", "联系电话"
            };

            // 创建表头行 (第0行)
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
            }

            // 3. 从数据库查询所有客户数据
            List<Client> clientList = clientDao.selectList(null);

            // 4. 遍历数据并填充到Excel的行和单元格中
            int rowNum = 1; // 数据从第1行开始 (第0行是表头)
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 用于格式化日期

            for (Client client : clientList) {
                Row row = sheet.createRow(rowNum++);

                // 填充每一列的数据，并进行null值检查
                row.createCell(0).setCellValue(client.getClientId() != null ? client.getClientId() : 0);
                row.createCell(1).setCellValue(client.getClientName() != null ? client.getClientName() : "");
                row.createCell(2).setCellValue(client.getClientType() != null ? client.getClientType() : "");
                row.createCell(3).setCellValue(client.getClientGender() != null ? client.getClientGender() : "");
                row.createCell(4).setCellValue(client.getClientAge() != null ? client.getClientAge() : 0);
                row.createCell(5).setCellValue(client.getDateOfBirth() != null ? sdf.format(client.getDateOfBirth()) : "");
                row.createCell(6).setCellValue(client.getClientCardNumber() != null ? client.getClientCardNumber() : "");
                row.createCell(7).setCellValue(client.getBloodType() != null ? client.getBloodType() : "");
                row.createCell(8).setCellValue(client.getFamilyMember() != null ? client.getFamilyMember() : "");
                row.createCell(9).setCellValue(client.getClientPhone() != null ? client.getClientPhone() : "");
            }

            // 5. 将整个工作簿 (Workbook) 的内容写入到内存中的字节数组输出流
            workbook.write(outputStream);

            // 6. 将生成的字节数组包装在ResponseBean中成功返回
            return new ResponseBean<>(outputStream.toByteArray());

        } catch (Exception e) {
            e.printStackTrace();
            // 如果发生任何异常，返回一个包含错误信息的ResponseBean
            return new ResponseBean<>(500, "生成Excel文件失败: " + e.getMessage());
        }
    }
    @Override
    public ResponseBean<List<Client>> getClientsByRoom(String roomId) {
        try {
            // 直接调用DAO层的新方法
            List<Client> clients = clientDao.findClientsByRoomId(roomId);
            return new ResponseBean<>(clients);
        } catch (Exception e) {
            // 记录日志并返回统一的错误响应
            return new ResponseBean<>(500, "获取房间客户信息失败：" + e.getMessage());
        }
    }

    @Override
    public ResponseBean<List<Client>> listAll() {
        List<Client> list = clientDao.selectList(null);
        return new ResponseBean<>(list);
    }

    @Override
    public ResponseBean<IPage<Client>> listUnassignedCareClients(String name, long page, long size) {
        // 1. 分页对象
        Page<Client> pager = new Page<>(page, size);

        // 2. 构造查询条件
        QueryWrapper<Client> qw = new QueryWrapper<>();
        qw.eq("client_type", "护理");
        qw.isNull("care_admin_id");
        if (name != null && !name.isBlank()) {
            qw.like("client_name", name.trim());
        }

        // 3. 执行分页查询
        return new ResponseBean<>(clientDao.selectPage(pager, qw));
    }

    @Override
    public ResponseBean<Client> getById(Integer id) {
        Client client = clientDao.selectById(id);
        if (client == null) {
            return new ResponseBean<>(404, "客户未找到");
        }
        return new ResponseBean<>(client);
    }

    @Override
    public ResponseBean<Void> create(Client client) {
        int rows = clientDao.insert(client);
        if (rows != 1) {
            return new ResponseBean<>(500, "创建失败");
        }
        return new ResponseBean<>();
    }

    @Override
    public ResponseBean<Void> update(Client client) {
        int rows = clientDao.updateById(client);
        if (rows != 1) {
            return new ResponseBean<>(500, "更新失败");
        }
        return new ResponseBean<>();
    }

    @Override
    public ResponseBean<Void> delete(Integer id) {
        int rows = clientDao.deleteById(id);
        if (rows != 1) {
            return new ResponseBean<>(500, "删除失败");
        }
        return new ResponseBean<>();
    }

    // 设置客户护理级别
    @Override
    public ResponseBean<Integer> setCareLevelId(@RequestParam Integer clientId, @RequestParam Integer careLevelId) {
        System.out.println("调试：设置客户护理级别");
        Client client = clientDao.selectById(clientId);
        if (client == null) {
            return new ResponseBean<>(500, "未找到指定的客户");
        }
        client.setCareLevelId(careLevelId);
        int updateResult = clientDao.updateById(client);
        if (updateResult > 0) {
            return new ResponseBean<>(updateResult);
        } else {
            return new ResponseBean<>(500, "设置客户护理级别失败");
        }
    }

    // 移除客户护理级别
    @Override
    public ResponseBean<Integer> deleteCareLevelId(Integer clientId) {
        System.out.println("调试：移除客户护理级别");
        UpdateWrapper<Client> uw=new UpdateWrapper<>();
        uw.eq("client_id", clientId).set("care_level_id",null);
        int updateResult = clientDao.update(null, uw);
        System.out.println("更新结果：" + updateResult);
        if (updateResult > 0) {
            // 移除护理级别时，删除客户护理项目（客户护理项目都是这个级别下的）
            int deleteCareItemsResult = clientCareItemDao.deleteClientCareItemsByClientId(clientId);
            return new ResponseBean<>(updateResult);
        } else {
            return new ResponseBean<>(500, "移除客户护理级别失败");
        }
    }

//    // 根据客户姓名查询护理老人列表
//    @Override
//    public ResponseBean<List<ClientWithCareLevel>> searchByNameAndCareType(String clientName, String careType) {
//        List<ClientWithCareLevel> clients = clientDao.searchByNameAndCareType(clientName, careType);
//        return new ResponseBean<>(clients);
//    }

    // 根据客户姓名查询护理老人列表
    @Override
    public ResponseBean<IPage<ClientWithCareLevel>> searchByNameAndCareType(String clientName, String careType, long page, long size) {
//        List<ClientWithCareLevel> clients = clientDao.searchByNameAndCareType(clientName, careType);
//        return new ResponseBean<>(clients);


        // 计算分页的偏移量
        long offset = (page - 1) * size;

        // 调用分页查询方法
        List<ClientWithCareLevel> ClientWithCareLevel = clientDao.searchByNameAndCareType(clientName, careType, offset, size);

        // 查询总记录数
        int total = clientDao.countSearchByNameAndCareType(clientName, careType);

        // 将查询结果封装到分页对象中
        IPage<ClientWithCareLevel> iPage = new Page<>(page, size);
        iPage.setRecords(ClientWithCareLevel);
        iPage.setTotal(total);
        System.out.println("total"+iPage.getTotal()+"pages"+iPage.getPages());

        return new ResponseBean<>(iPage);
    }


    // 根据客户姓名查询护理老人列表
    @Override
    public ResponseBean<IPage<ClientWithCareLevel>> searchByNameAndCareTypeAndAdId(String clientName, String careType,Integer adId, long page, long size) {
//        List<ClientWithCareLevel> clients = clientDao.searchByNameAndCareType(clientName, careType);
//        return new ResponseBean<>(clients);


        // 计算分页的偏移量
        long offset = (page - 1) * size;

        // 调用分页查询方法
        List<ClientWithCareLevel> ClientWithCareLevel = clientDao.searchByNameAndCareTypeAndAdId(clientName, careType, adId, offset, size);

        // 查询总记录数
        int total = clientDao.countSearchByNameAndCareTypeAndAdId(clientName, careType, adId);

        // 将查询结果封装到分页对象中
        IPage<ClientWithCareLevel> iPage = new Page<>(page, size);
        iPage.setRecords(ClientWithCareLevel);
        iPage.setTotal(total);
        System.out.println("total"+iPage.getTotal()+"pages"+iPage.getPages());

        return new ResponseBean<>(iPage);
    }


}
